package com.fan.cachewebview.pool

import android.graphics.Bitmap
import android.net.http.SslError
import android.os.Build
import android.os.Message
import android.text.TextUtils
import android.view.KeyEvent
import android.webkit.*
import androidx.annotation.RequiresApi
import com.fan.cachewebview.core.WebResourceCacheImpl
import com.fan.cachewebview.core.CacheOpenApi
import com.fan.cachewebview.core.DestroyApi
import com.fan.cachewebview.core.WebResourceCacheApi
import com.fan.cachewebview.core.CacheConfig
import com.fan.cachewebview.core.CacheMode
import com.fan.cachewebview.core.interceptor.ResourceInterceptor

/**
 * @description  WebViewClient intercept资源处理为止
 * @date: 2022/2/23 15:17
 * @author: fan
 */
open class CacheWebViewClient : WebViewClient, CacheOpenApi, DestroyApi {


    private val SCHEME_HTTP = "http"
    private val SCHEME_HTTPS = "https"
    private val METHOD_GET = "GET"
    private var mDelegate: WebViewClient? = null
    private var mWebViewCache: WebResourceCacheApi? = null
    private var mWebViewCacheMode = 0
    private var mUserAgent: String? = null
    private var mOwner: CacheWebView? = null

    constructor(owner: CacheWebView) {
        mOwner = owner
        val settings: WebSettings = owner.settings
        mWebViewCacheMode = settings.cacheMode
        mUserAgent = settings.userAgentString

        mWebViewCache = WebResourceCacheImpl(owner.context, owner)
    }

    fun updateProxyClient(webViewClient: WebViewClient?) {
        mDelegate = webViewClient
    }

    @Suppress("DEPRECATION")
    override fun onTooManyRedirects(view: WebView?, cancelMsg: Message?, continueMsg: Message?) {
        if (mDelegate != null) {
            mDelegate!!.onTooManyRedirects(view, cancelMsg, continueMsg)
            return
        }
        super.onTooManyRedirects(view, cancelMsg, continueMsg)
    }




    @RequiresApi(api = Build.VERSION_CODES.M)
    override fun onReceivedHttpError(
        view: WebView?,
        request: WebResourceRequest?,
        errorResponse: WebResourceResponse?
    ) {
        if (mDelegate != null) {
            mDelegate!!.onReceivedHttpError(view, request, errorResponse)
            return
        }
        super.onReceivedHttpError(view, request, errorResponse)
    }


    override fun onFormResubmission(view: WebView?, dontResend: Message?, resend: Message?) {
        if (mDelegate != null) {
            mDelegate!!.onFormResubmission(view, dontResend, resend)
            return
        }
        super.onFormResubmission(view, dontResend, resend)
    }

    override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
        if (mDelegate != null) {
            mDelegate!!.doUpdateVisitedHistory(view, url, isReload)
            return
        }
        super.doUpdateVisitedHistory(view, url, isReload)
    }

    override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
        if (mDelegate != null) {
            mDelegate!!.onReceivedSslError(view, handler, error)
            return
        }
        super.onReceivedSslError(view, handler, error)
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    override fun onReceivedClientCertRequest(view: WebView?, request: ClientCertRequest?) {
        if (mDelegate != null) {
            mDelegate!!.onReceivedClientCertRequest(view, request)
            return
        }
        super.onReceivedClientCertRequest(view, request)
    }

    override fun onReceivedHttpAuthRequest(
        view: WebView?,
        handler: HttpAuthHandler?,
        host: String?,
        realm: String?
    ) {
        if (mDelegate != null) {
            mDelegate!!.onReceivedHttpAuthRequest(view, handler, host, realm)
            return
        }
        super.onReceivedHttpAuthRequest(view, handler, host, realm)
    }


    override fun shouldOverrideKeyEvent(view: WebView?, event: KeyEvent?): Boolean {
        return if (mDelegate != null) {
            mDelegate!!.shouldOverrideKeyEvent(view, event)
        } else super.shouldOverrideKeyEvent(view, event)
    }

    override fun onUnhandledKeyEvent(view: WebView?, event: KeyEvent?) {
        if (mDelegate != null) {
            mDelegate!!.onUnhandledKeyEvent(view, event)
            return
        }
        super.onUnhandledKeyEvent(view, event)
    }

    override fun onScaleChanged(view: WebView?, oldScale: Float, newScale: Float) {
        if (mDelegate != null) {
            mDelegate!!.onScaleChanged(view, oldScale, newScale)
            return
        }
        super.onScaleChanged(view, oldScale, newScale)
    }

    override fun onReceivedLoginRequest(
        view: WebView?,
        realm: String?,
        account: String?,
        args: String?
    ) {
        if (mDelegate != null) {
            mDelegate!!.onReceivedLoginRequest(view, realm, account, args)
            return
        }
        super.onReceivedLoginRequest(view, realm, account, args)
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    override fun onRenderProcessGone(view: WebView?, detail: RenderProcessGoneDetail?): Boolean {
        return if (mDelegate != null) {
            mDelegate!!.onRenderProcessGone(view, detail)
        } else super.onRenderProcessGone(view, detail)
    }

    @Suppress("DEPRECATION")
    override fun onReceivedError(
        view: WebView?,
        errorCode: Int,
        description: String?,
        failingUrl: String?
    ) {
        if (mDelegate != null) {
            mDelegate!!.onReceivedError(view, errorCode, description, failingUrl)
            return
        }
        super.onReceivedError(view, errorCode, description, failingUrl)
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    override fun onReceivedError(
        view: WebView?,
        request: WebResourceRequest?,
        error: WebResourceError?
    ) {
        if (mDelegate != null) {
            mDelegate!!.onReceivedError(view, request, error)
            return
        }
        super.onReceivedError(view, request, error)
    }

    override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
        if (mDelegate != null) {
            mDelegate!!.onPageStarted(view, url, favicon)
            return
        }
        super.onPageStarted(view, url, favicon)
    }

    override fun onPageFinished(view: WebView?, url: String) {
        if (mOwner!!.isRecycled() && url != "about:blank") {
            mOwner!!.setRecycled(false)
            mOwner!!.clearHistory()
        }
        if (mDelegate != null) {
            mDelegate!!.onPageFinished(view, url)
            return
        }
        super.onPageFinished(view, url)
    }

    override fun onLoadResource(view: WebView?, url: String?) {
        if (mDelegate != null) {
            mDelegate!!.onLoadResource(view, url)
            return
        }
        super.onLoadResource(view, url)
    }


    override fun onPageCommitVisible(view: WebView?, url: String?) {
        if (mDelegate != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mDelegate!!.onPageCommitVisible(view, url)
            return
        }
        super.onPageCommitVisible(view, url)
    }

    @Suppress("DEPRECATION")
    override fun shouldOverrideUrlLoading(view: WebView, url: String?): Boolean {
        if (mDelegate != null) {
            return mDelegate!!.shouldOverrideUrlLoading(view, url)
        }
        if (!TextUtils.isEmpty(url)){
            view.loadUrl(url.toString())
        }
        return true
    }


    @RequiresApi(api = Build.VERSION_CODES.N)
    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
        if (mDelegate != null) {
            return mDelegate!!.shouldOverrideUrlLoading(view, request)
        }
        view.loadUrl(request.url.toString())
        return true
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    override fun shouldInterceptRequest(
        view: WebView?,
        request: WebResourceRequest?
    ): WebResourceResponse? {
        return onIntercept(view, request)
    }


    // 核心方法：拦截处理！
    private fun onIntercept(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
        if (mDelegate != null) {
            var response = mDelegate!!.shouldInterceptRequest(view, request)
            if (response != null) {
                return response
            }
        }
        return loadFromWebViewCache(request)
    }

    private fun loadFromWebViewCache(request: WebResourceRequest?): WebResourceResponse? {
        var scheme = request?.url?.scheme?.trim()
        var method = request?.method?.trim()
        if ((TextUtils.equals(SCHEME_HTTP, scheme) || TextUtils.equals(SCHEME_HTTPS, scheme))
            && method.equals(METHOD_GET, ignoreCase = true)
        ) {
            return mWebViewCache!!.getResource(request!!, mWebViewCacheMode, mUserAgent!!)
        }
        return null
    }


    override fun setCacheMode(mode: CacheMode, config: CacheConfig?) {
        if (mWebViewCache != null){
            mWebViewCache!!.setCacheMode(mode,config)
        }
    }

    override fun addResourceInterceptor(interceptor: ResourceInterceptor) {
        if (mWebViewCache != null){
            mWebViewCache!!.addResourceInterceptor(interceptor)
        }
    }

    override fun destroy() {
        if (mWebViewCache != null){
            mWebViewCache!!.destroy()
        }
    }
}